//Brian Goodacre

package data;

import java.util.ArrayList;
import java.util.List;

import settings.Global;

public class DiskPage {
	//needed for all DiskPages
	private final static int max_DataPoints = (Global.disk_bytes + 2) /DataPoint.size_bytes; //2 for pointers
	
	//constructor variables
	private List<DataPoint> disk_data;
	private int num_DataPoints;
	private DiskPage prev;
	private DiskPage next;
	
	//CONSTRUCTOR that is pretty empty
	public DiskPage() {
		num_DataPoints=0;
		disk_data = new ArrayList<DataPoint>(); //allocate memory
		prev = null;
		next = null;
	}
	
	

	//FUNCTIONS
	//getters and some setters
	public List<DataPoint> getDisk_data() { return disk_data;}
	public int getNum_DataPoints() {return num_DataPoints; }	
	public DiskPage getPrev() {return prev;}
	public void setPrev(DiskPage prev) {this.prev = prev;}
	public DiskPage getNext() {return next;}
	public void setNext(DiskPage next) {this.next = next;}


	//add a datapoint to the DiskPage, return true=success, false=failure(full disk)
	public boolean addDataPoint(DataPoint datapoint){
		if(num_DataPoints < max_DataPoints){//not full, can add
			disk_data.add(datapoint);
			return true;
		}
		else{
			return false;
		}
	}
	
	//add an ArrayList<DataPoint> for bulk loading to a diskPage
	public boolean addManyDataPoints(List<DataPoint> al_datapoint){
		if( (al_datapoint.size()+num_DataPoints) < max_DataPoints ){ //have room, can add
			disk_data.addAll(al_datapoint);//append to the end
			return true;
		}
		else{//cannot add
			return false;
		}
	}

	//get first hilbert value
	public long getFirstValue(){
		return disk_data.get(0).getHilbert_value();
	}
	
	//get last hilbert value
	public long getLastValue(){
		return disk_data.get(disk_data.size()-1).getHilbert_value();
	}

	//takes in ArrayList<DataPoint> and creates a lot of full DiskPages
	public static ArrayList<DiskPage> dataPoints_to_diskPages (List<DataPoint> al_datapoints){
		//allocate memory
		ArrayList<DiskPage> al_diskpages = new ArrayList<DiskPage>();
		int min_sublist;
		int max_sublist;
		
		//create disk pages
		for(int i=0;i<al_datapoints.size();i=i+max_DataPoints){//go through all datapoints
			min_sublist = i;
			max_sublist = i+max_DataPoints-1; //max until the end
			if(max_sublist>al_datapoints.size()) max_sublist = al_datapoints.size()-1; //reduce if beyond boundary
			
			DiskPage diskpage = new DiskPage(); //allocate memory
			diskpage.addManyDataPoints(al_datapoints.subList(min_sublist, max_sublist)); //add
			al_diskpages.add(diskpage); //add to the ArrayList<DiskPage> that will be returned
		}
		
		//make doubly linked list for diskpages
		for(int j=0;j<al_diskpages.size();j++){
			//check bounds and then set
			if(j!=0) al_diskpages.get(j).setPrev(al_diskpages.get(j-1));
			if(j!=al_diskpages.size()-1) al_diskpages.get(j).setNext(al_diskpages.get(j+1));
		}
		
		return al_diskpages; //finished
	}
}
